package com.tamtamy.jttamobile.parser;

import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.tamtamy.jttamobile.JTTAClient;
import com.tamtamy.jttamobile.data.Comment;
import com.tamtamy.jttamobile.data.CommentList;
import com.tamtamy.jttamobile.data.Content;
import com.tamtamy.jttamobile.data.ContentFile;
import com.tamtamy.jttamobile.data.ContentLink;
import com.tamtamy.jttamobile.data.ContentList;
import com.tamtamy.jttamobile.data.ContentMessage;
import com.tamtamy.jttamobile.data.ContentQuestion;
import com.tamtamy.jttamobile.data.ContentWidget;
import com.tamtamy.jttamobile.data.Group;
import com.tamtamy.jttamobile.data.GroupDetails;
import com.tamtamy.jttamobile.data.GroupList;
import com.tamtamy.jttamobile.data.Metadata;
import com.tamtamy.jttamobile.data.Network;
import com.tamtamy.jttamobile.data.NetworkDetails;
import com.tamtamy.jttamobile.data.NetworkList;
import com.tamtamy.jttamobile.data.Notice;
import com.tamtamy.jttamobile.data.NoticeList;
import com.tamtamy.jttamobile.data.OnLineUsersList;
import com.tamtamy.jttamobile.data.OnlineUser;
import com.tamtamy.jttamobile.data.TagDetail;
import com.tamtamy.jttamobile.data.TagList;
import com.tamtamy.jttamobile.data.Token;
import com.tamtamy.jttamobile.data.User;
import com.tamtamy.jttamobile.data.UserDetail;
import com.tamtamy.jttamobile.data.UserStats;
import com.tamtamy.jttamobile.data.UserStatsGeneration;
import com.tamtamy.jttamobile.data.UserStatsGenerationDetails;
import com.tamtamy.jttamobile.data.UserStatsGenerationList;
import com.tamtamy.jttamobile.data.UserStatsList;
import com.tamtamy.jttamobile.data.UserTag;
import com.tamtamy.jttamobile.data.UsersList;
import com.tamtamy.jttamobile.data.json.JSONListFactory;
import com.tamtamy.jttamobile.data.json.JSONTagList;
import com.tamtamy.jttamobile.exception.JTTAException;
import com.tamtamy.jttamobile.exception.NoResultException;
import com.tamtamy.jttamobile.exception.ParsingException;
import com.tamtamy.jttamobile.exception.UnauthorizedException;
import com.tamtamy.jttamobile.utility.APIUtility;

/**
 * @author a.pellegatta
 *
 */
public class JSONParser implements Parser {

	private APIUtility apiUtility;
	
	public JSONParser(APIUtility utility) {
		this.apiUtility = utility;
	}
	
	

	@Override
	public Object getData(String url) throws JTTAException {
		HttpGet httpRequest = new HttpGet(url);
		JSONObject jsonObject = new JSONObject();
		String response = JTTAClient.getResponse(httpRequest);	
		try {
			jsonObject = new JSONObject(response);
		}
		catch (Exception exception) {
			Log.e(this.getClass().getSimpleName(), exception.getLocalizedMessage(), exception);
			throw new JTTAException("Error parsing " + url + " : " + exception.getLocalizedMessage());
		}
		return jsonObject;
	}
	
	public Object getDataPost(String url, List<NameValuePair> nameValuePairs) throws JTTAException {
		JSONObject jsonObject;
		try {
			HttpPost httppost = new HttpPost(url);    
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, JTTAClient.DEF_ENCODING));
			String response = JTTAClient.getResponse(httppost);	
			jsonObject = new JSONObject(response);
		}
		catch (Exception exception) {
			Log.e(this.getClass().getSimpleName(), exception.getLocalizedMessage(), exception);
			throw new JTTAException("Error parsing " + url + " : " + exception.getLocalizedMessage());
		}
		return jsonObject;
	}
	
	@Override
	public Token doLogin(String username, String password) throws UnauthorizedException  {
		String loginURL = apiUtility.getLoginURL(username, password);
		Token token = new Token();
		try {
			JSONObject loginJSON = (JSONObject)getData(loginURL);  
			PropertyInjector.populateObject(token, loginJSON);
			apiUtility.setToken(token);
		} catch (JTTAException e) {
			UnauthorizedException pe = new UnauthorizedException(e.getMessage());
			pe.initCause(e);
			throw pe;
		}
		
		return token;
	}
	
	public Token tryLogin(String tamtamyUrl, String username, String password) throws UnauthorizedException  {
		String loginURL = apiUtility.getLoginURL(tamtamyUrl, username, password);
		Token token = new Token();
		try {
			JSONObject loginJSON = (JSONObject)getData(loginURL);  
			PropertyInjector.populateObject(token, loginJSON);
			apiUtility.setToken(token);
		} catch (JTTAException e) {
			UnauthorizedException pe = new UnauthorizedException(e.getMessage());
			pe.initCause(e);
			throw pe;
		}
		
		return token;
	}
	
	@Override
	public boolean isValidToken(String username, String token) {
		try {
			apiUtility.setToken(new Token(token));
			String userDetailURL = apiUtility.getUserDetailURL(username);
			getData(userDetailURL);
			return true;
		} catch (JTTAException unauthorizedException) {
			return false;
		}
	}

	@Override
	public void doLogout() throws JTTAException {
		String logoutURL = apiUtility.getLogoutURL();
		getData(logoutURL);
	}

	@Override
	public void downloadContent(String contentID) throws JTTAException {
		String downloadContentURL = apiUtility.getDownloadContentURL(contentID);
		getData(downloadContentURL);
	}

	@Override
	public Comment getComment(long commentID) throws JTTAException, ParsingException {
		Comment comment = new Comment();
		String commentURL = apiUtility.getCommentURL(commentID);
		JSONObject commentJSON = (JSONObject) getData(commentURL);
		PropertyInjector.populateObject(comment, commentJSON);
		return comment;	
	}

	@Override
	public CommentList getCommentList(long startOffset, long limit)	throws JTTAException, ParsingException {
		CommentList commentList = new CommentList();
		String commentListURL = apiUtility.getCommentListURL(startOffset, limit);
		JSONObject commentListJSON = (JSONObject) getData(commentListURL);
		PropertyInjector.populateObject(commentList, commentListJSON);
		
		return commentList;	
	}
	
	@Override
	public CommentList getCommentsList(long contentID, long startOffset, long limit) throws JTTAException, ParsingException {
		CommentList commentList = new CommentList();
		String commentListURL = apiUtility.getCommentsListURL(contentID, startOffset, limit);
		JSONObject commentListJSON = (JSONObject) getData(commentListURL);
		try {
			commentList = new JSONListFactory<CommentList, Comment>(CommentList.class,Comment.class).createFactory(commentListJSON, "list");
		} catch (NoResultException e) {
			e.printStackTrace();
		}
		//PropertyInjector.populateObject(commentList, commentListJSON);
		Log.d("TEST", commentList.toString());
		return commentList;	
	}

	@Override
	public Content getContent(String contentID)	throws JTTAException {
		Content content = null;
		String contentFileURL = apiUtility.getContentURL(contentID);
		JSONObject contentFileJSON =  (JSONObject) getData(contentFileURL);
		try {
			String contentType = contentFileJSON.getString("contentType");
			if(Content.CONTENT_FILTER_LINK.equals(contentType)){
				content = new ContentLink();
				PropertyInjector.populateObject(content, contentFileJSON);
			}else if(Content.CONTENT_FILTER_DOCUMENT.equals(contentType)){
				content = new ContentFile();
				PropertyInjector.populateObject(content, contentFileJSON);
			}else if(Content.CONTENT_FILTER_MESSAGE.equals(contentType)){
				content = new ContentMessage();
				PropertyInjector.populateObject(content, contentFileJSON);
			}else if(Content.CONTENT_FILTER_QUESTION.equals(contentType)){
				content = new ContentQuestion();
				PropertyInjector.populateObject(content, contentFileJSON);
			}else if(Content.CONTENT_FILTER_AUDIO.equals(contentType)){
				content = new ContentFile();
				PropertyInjector.populateObject(content, contentFileJSON);
			}else if(Content.CONTENT_FILTER_VIDEO.equals(contentType)){
				
				content = new ContentFile();
				PropertyInjector.populateObject(content, contentFileJSON);
			}else if(Content.CONTENT_FILTER_UWA.equals(contentType)){
				content = new ContentWidget();
				PropertyInjector.populateObject(content, contentFileJSON);
			}else {
				content = new Content();
				PropertyInjector.populateObject(content, contentFileJSON);
			}
		} catch (JSONException e) {
			new ParsingException(e.getMessage());
		}
		return content;	
	}
	
	@Override
	public Content getContentFile(String contentID)	throws JTTAException {
		Content contentFile = new ContentFile();
		String contentFileURL = apiUtility.getContentFileURL(contentID);
		JSONObject contentFileJSON =  (JSONObject) getData(contentFileURL);
		PropertyInjector.populateObject(contentFile,contentFileJSON);
		return contentFile;	
	}

	@Override
	public ContentLink getContentLink(String contentID)	throws JTTAException {
		ContentLink contentLink = new ContentLink();
		String contentLinkURL = apiUtility.getContentLinkURL(contentID);
		JSONObject contentLinkJSON =  (JSONObject) getData(contentLinkURL);
		PropertyInjector.populateObject(contentLink,contentLinkJSON);
		return contentLink;	
	}

	@Override
	public ContentList getContentList(long startOffset, long limit, String filter, String order) throws JTTAException,ParsingException {
		ContentList contentList = null;
		String contentURL = apiUtility.getContentListURL(startOffset, limit, filter, order);
		try{
			JSONObject contentListJSON = (JSONObject) getData(contentURL);
			contentList = new JSONListFactory<ContentList, Content>(ContentList.class,Content.class).createFactory(contentListJSON, "list");
		} catch (NoResultException noResultException) {
			Log.d(this.getClass().getSimpleName(), "-------------------------->" + noResultException.getMessage(), noResultException);
			contentList = new ContentList();
		}
		return contentList;	
	}

	@Override
	public ContentMessage getContentMessage(String contentID) throws JTTAException {
		ContentMessage contentMessage = new ContentMessage();
		String contentMessageURL = apiUtility.getContentMessageURL(contentID);
		JSONObject contentMessageJSON =  (JSONObject) getData(contentMessageURL);
		PropertyInjector.populateObject(contentMessage,contentMessageJSON);
		return contentMessage;
	}

	@Override
	public ContentWidget getContentWidget(String contentID)	throws JTTAException {
		ContentWidget  contentWidget = new ContentWidget();
		String contentWidgetURL = apiUtility.getContentWidgetURL(contentID);
		JSONObject contentWidgetJSON =  (JSONObject) getData(contentWidgetURL);
		PropertyInjector.populateObject(contentWidget ,contentWidgetJSON);
		return  contentWidget;	
	}
	
	@Override
	public GroupDetails getGroupDetails(String groupID)	throws JTTAException {
		GroupDetails groupDetails = new GroupDetails();
		String groupDetailsURL = apiUtility.getGroupDetailsURL(groupID);				
		JSONObject groupDetailsJSON = (JSONObject) getData(groupDetailsURL);
		PropertyInjector.populateObject(groupDetails, groupDetailsJSON);
		return groupDetails;	
	}

	@Override
	public GroupList getGroupList(long startOffset, long limit)	throws JTTAException, ParsingException {
		GroupList groupList = null;
		String groupListURL = apiUtility.getGroupListURL(startOffset, limit);		
		try {
			JSONObject groupListJSON = (JSONObject) getData(groupListURL);
			groupList = new JSONListFactory<GroupList, Group>(GroupList.class,Group.class).createFactory(groupListJSON, "list");
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		} 
		return groupList;	
	}

	@Override
	public Metadata getMetadata(String url) throws JTTAException, ParsingException {
		Metadata metadata = new Metadata();
		try {
			String metadataURL = apiUtility.getMetadataURL(url);
			JSONObject metadataJSON = (JSONObject) getData(metadataURL);
			PropertyInjector.populateObject(metadata ,metadataJSON);
		} catch (Exception exception) {
			throw new ParsingException(exception.getMessage());
		}
		return metadata;
	}

	@Override
	public NetworkDetails getNetworkDetails(String networkID) throws JTTAException {
		NetworkDetails networkDetails = new NetworkDetails();
		String networkDetailsURL = apiUtility.getNetworkDetailsURL(networkID);				
		JSONObject networkDetailsJSON = (JSONObject) getData(networkDetailsURL);
		PropertyInjector.populateObject(networkDetails ,networkDetailsJSON);
		return networkDetails;	
	}

	@Override
	public NetworkList getNetworkList(long startOffset, long limit) throws JTTAException, ParsingException {
		NetworkList networkList = null;
		String networkListURL = apiUtility.getNetworkListURL(startOffset, limit);
		try {
			JSONObject networkListJSON = (JSONObject) getData(networkListURL);
			networkList = new JSONListFactory<NetworkList, Network>(NetworkList.class, Network.class).createFactory(networkListJSON, "list");
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		} 
		return networkList;	
	}

	
	@Override
	public NetworkList getNetworkList(long startOffset, long limit, String filter) throws JTTAException, ParsingException {
		NetworkList networkList = new NetworkList();
		String networkListURL = apiUtility.getNetworkListURL(startOffset, limit, filter);
		try {
			JSONObject networkListJSON = (JSONObject) getData(networkListURL);
			networkList = new JSONListFactory<NetworkList, Network>(NetworkList.class, Network.class).createFactory(networkListJSON, "list");
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		}
		return networkList;	
	}
	
	@Override
	public NetworkList getNetworkListWithChatEnabled(long startOffset, long limit) throws JTTAException, ParsingException {
		NetworkList networkListWithChatEnabled = new NetworkList();
		String networkListWithChatEnableURL = apiUtility.getNetworkListWithChatEnabledURL(startOffset, limit);
		try {
			JSONObject networkListWithChatEnabledJSON = (JSONObject) getData(networkListWithChatEnableURL);
			networkListWithChatEnabled = new JSONListFactory<NetworkList, Network>(NetworkList.class, Network.class).createFactory(networkListWithChatEnabledJSON, "list");
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		} 
		return networkListWithChatEnabled;	
	}

	
	@Override
	public NetworkList getNetworkListWithChatEnabled(long startOffset, long limit, String filter) throws JTTAException, ParsingException {
		NetworkList networkListWithChatEnabled = null;
		String networkListWithChatEnableURL = apiUtility.getNetworkListWithChatEnabledURL(startOffset, limit, filter);
		try {
			JSONObject networkListWithChatEnabledJSON = (JSONObject) getData(networkListWithChatEnableURL);
			networkListWithChatEnabled = new JSONListFactory<NetworkList, Network>(NetworkList.class, Network.class).createFactory(networkListWithChatEnabledJSON, "list");
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		} 
		return networkListWithChatEnabled;	
	}
	
	@Override
	public Notice getNotice(long noticeID) throws JTTAException {
		Notice notice = new Notice();
		String noticeURL = apiUtility.getNoticeURL(noticeID);	
		JSONObject noticeJSON = (JSONObject) getData(noticeURL);
		PropertyInjector.populateObject(notice ,noticeJSON);
		return notice;	
	}

	@Override
	public NoticeList getNoticeList(long startOffset, long limit, String filter, String userId, String fromDate, String toDate) throws JTTAException, ParsingException {
		NoticeList noticeList = null;
		String noticeListURL = apiUtility.getNoticeListURL(startOffset, limit, filter, userId, fromDate, toDate);	
		try {
			JSONObject noticeListJSON = (JSONObject) getData(noticeListURL);
			noticeList = new JSONListFactory<NoticeList, Notice>(NoticeList.class, Notice.class).createFactory(noticeListJSON, "list");
		}catch (NoResultException noResultException) {
			// TODO some actions?	
		} 
		return noticeList;	
	}

	@Override
	public OnLineUsersList getOnLineUsersList(long startOffset, long limit)	throws JTTAException {
		OnLineUsersList onLineUsersList = null;
		String onlineUsersListURL = apiUtility.getOnlineUsersList(startOffset, limit);
		JSONObject onLineUsersListJSON =  (JSONObject) getData(onlineUsersListURL);			
		try{
			onLineUsersList = new JSONListFactory<OnLineUsersList, OnlineUser>(OnLineUsersList.class, OnlineUser.class).createFactory(onLineUsersListJSON, "list");
		}catch(NoResultException nre){
			
		}
		return onLineUsersList;
	}


	@Override
	public TagDetail getTagDetail(String tag) throws JTTAException {
		TagDetail tagDetail = new TagDetail();
		String tagListDetailURL = apiUtility.getTagListDetailURL(tag);
		JSONObject tagDetailJSON =  (JSONObject) getData(tagListDetailURL);
		PropertyInjector.populateObject(tagDetail ,tagDetailJSON);
		return tagDetail;
	}


	@Override
	public TagList getTagList(long startOffset, long limit)	throws JTTAException {
		TagList tagList = new TagList();
		String tagListURL = apiUtility.getTagListURL(startOffset, limit);
		JSONObject tagListJSON =  (JSONObject) getData(tagListURL);
		try {
			tagList = new JSONTagList(tagListJSON);
		} catch (JSONException e) {
			new ParsingException(e.getMessage());
		}
		return tagList;		
	}


	@Override
	public UserDetail getUserDetail(String userID) throws JTTAException {
		UserDetail userDetail = new UserDetail();
		String userDetailURL = apiUtility.getUserDetailURL(userID);
		JSONObject userDetailJSON = (JSONObject) getData(userDetailURL);
		PropertyInjector.populateObject(userDetail, userDetailJSON);
		return userDetail;	
	}

	@Override
	public UserStatsGenerationDetails getUserStatsGenerationDetails(String userStatsID, long startOffset, long limit) throws JTTAException {
		UserStatsGenerationDetails userStatsGenerationDetails = new UserStatsGenerationDetails();
		String userStatsGenerationDetailsURL = apiUtility.getUserStatsGenerationDetailsURL(userStatsID, startOffset, limit);		
		JSONObject userStatsGenerationDetailsJSON = (JSONObject) getData(userStatsGenerationDetailsURL);
		PropertyInjector.populateObject(userStatsGenerationDetails ,userStatsGenerationDetailsJSON);
		return userStatsGenerationDetails;	
	}

	@Override
	public UserStatsGenerationList getUserStatsGenerationList(long startOffset,	long limit) throws JTTAException, ParsingException {
		UserStatsGenerationList userStatsGenerationList = new UserStatsGenerationList();
		String userStatsGenerationListURL = apiUtility.getUserStatsGenerationListURL(startOffset, limit);
		try {
			JSONObject userStatsGenerationListJSON = (JSONObject) getData(userStatsGenerationListURL);
			userStatsGenerationList = new JSONListFactory<UserStatsGenerationList, UserStatsGeneration>(UserStatsGenerationList.class,UserStatsGeneration.class).createFactory(userStatsGenerationListJSON,"list");
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return userStatsGenerationList;	
	}

	@Override
	public UserStatsList getUserStatsList(String userID, long startOffset, long limit) throws JTTAException {
		UserStatsList userStats = new UserStatsList();
		String userStatsURL = apiUtility.getUserStatsURL(userID, startOffset, limit);
		try {
			JSONObject userStatsJSON = (JSONObject) getData(userStatsURL);
			userStats = new JSONListFactory<UserStatsList, UserStats>(UserStatsList.class, UserStats.class).createFactory(userStatsJSON, "list") ;	
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		} 
		return userStats;	
	}

	@Override
	public UserTag getUserTag(String filter) throws JTTAException {
		UserTag userTag = new UserTag();
		String userTagURL = apiUtility.getUserTagURL(filter);
		JSONObject userTagJSON = (JSONObject) getData(userTagURL);
		PropertyInjector.populateObject(userTag ,userTagJSON);
		return userTag;	
	}

	@Override
	public UserTag getUserTag(String userID, String filter)	throws JTTAException {
		UserTag userTag = new UserTag();
		String userTagURL = apiUtility.getUserTagURL(userID, filter);
		JSONObject userTagJSON = (JSONObject) getData(userTagURL);
		PropertyInjector.populateObject(userTag, userTagJSON);
		return userTag;	
	}

	@Override
	public UsersList getUsersList(long startOffset, long limit, String filter) throws JTTAException, ParsingException {
		UsersList userList = null;
		String userListURL = apiUtility.getUserListURL(startOffset, limit, filter);
		try {
			JSONObject userListJSON = (JSONObject) getData(userListURL);
			userList = new JSONListFactory<UsersList, User>(UsersList.class,User.class).createFactory(userListJSON,"list");
		} catch (NoResultException noResultException) {
			// TODO some actions?	
		}
		return userList;
	}

}
